#!/usr/bin/env python

import os
import sys

from pyparsing import alphas, alphanums, delimitedList, nums, oneOf, Or, Empty
from pyparsing import pythonStyleComment, quotedString, removeQuotes, restOfLine
from pyparsing import Combine, Group, Keyword, Literal, LineEnd, OneOrMore
from pyparsing import ParseFatalException, ParserElement, StringEnd, Forward
from pyparsing import Suppress, Word, ZeroOrMore, ParseException, Optional

keyword = lambda kword: Keyword(kword).suppress()

zones = []

def addZone(string, location, tokens):
   print(tokens)

def verifyZone(string, location, tokens):
   print(tokens)

def addAddressName(string, location, tokens):
   print(tokens)

def addSetName(string, location, tokens):
   print(tokens)

def addSetName(string, location, tokens):
   print(tokens)

def verifyAddressName(string, location, tokens):
   print(tokens)

def parseProtocols(string, location, tokens):
   print(tokens)

def parseAddress(string, location, tokens):
   print(tokens)

lb, rb = map(Suppress, "{}")
lp, rp = map(Suppress, "()")
lbk, rbk = map(Suppress, "[]")
lt, gt = map(Suppress, "<>")
quoted = quotedString.copy().setParseAction(removeQuotes)
protocols = Or(Word(alphas) + Group(Word(alphas) + "/" + Word(alphas)) + Group(
      Word(alphas) + "/" + Word(nums)) + Group(Word(nums) + "/" + Word(nums)))
allow = keyword("allow")
defines = Word(alphanums + "-" + "_")
ipaddress = Word(nums + "/" + ".")
zone = lt + defines + gt
comma = Suppress(",")
ruleopts = Or(keyword("log") + keyword("count") + Optional(comma))

zoneName = keyword("zone") + zone.setParseAction(addZone)
interface = Keyword("add") + keyword("interfaces")+ lbk + OneOrMore(
      Word(alphanums + "-" + "/" + ".") + Optional(comma)) + rbk + keyword(
            "to") + zone.setParseAction(verifyZone)

addressList = keyword("address") + zone.setParseAction(
   verifyZone) + defines.setParseAction(addAddressName) + ipaddress

addressSet = keyword("address-set") + zone.setParseAction(
   verifyZone) + defines.setParseAction(addSetName) + lbk + OneOrMore(
         defines.setParseAction(verifyAddressName) + Optional(comma)) + rbk

services = allow + keyword("service") + lbk + OneOrMore(
      Word(alphas) + Optional(comma)) + rbk + keyword(
            "on") + zone.setParseAction(verifyZone)

fwrule = allow + protocols.setParseAction(
   parseProtocols) + keyword("from") + defines.setParseAction(
      parseAddress) + keyword("to") + defines.setParseAction(
         parseAddress) + keyword("on") + zone.setParseAction(
            verifyZone) + keyword("name") + defines

ruleset = ZeroOrMore(
   zoneName + interface + ZeroOrMore(addressList) + ZeroOrMore(
      addressSet) + services + ZeroOrMore(fwrule))
ruleset.ignore(pythonStyleComment)

if __name__ == "__main__":
   filename = sys.argv[1]
   results = None
   try:
      with open(filename, "r") as fh:
         results = ruleset.parseString(fh.read())
   except ParseFatalException as err:
      print(err)
   except ParseException as err:
      print(err)
   else:
      print(results)

